import { IUITool } from "../base_frame/IUITool";
import { Keyboard } from "../base_frame/Keyboard";
import { ShaderTool } from "../base_frame/ShaderTool";
import { Vector3 } from "../base_frame/math/Vector3";
import { CameraEmulator } from "./CameraEmulator";
/**
 * 通过设置透视投影 调整显示窗口的内容
 * 
 * 也是可视空间的概念
 * 
 * 视点 表示相机的位置
 * 被查看的目标  表示相机看向的方向
 * up向量  表示相机正上方确定相机的旋转
 * 最终相机看向的方向和  canvas中的坐标系的 看向屏幕的z轴是 负方向是看向屏幕内的方向，数据会导致看向的方向不一致
 * 
 * 关于视野的解释:
 * 透视投影矩阵的本质是将三维场景投影到二维屏幕上，而这个投影过程是有视角角度决定的。在透视投影中，
 * 视角角度越小，所看到的场景越大，但离视点越远。视角角度越大，所看到的场景越小，但离视点越近。这
 * 是因为在透视投影中，投影的过程是从视点到物体的投影，视角角度越大，物体到视点的距离会缩短，因此
 * 物体在屏幕上的投影也会变小，而视角角度越小，物体到视点的距离会变长，因此物体在屏幕上的投影也会变大。
 * 
 * !! 存在问题
 * WebGL在默认情况下会按照缓冲区中的顺序绘制图形，而且后绘制的图形覆盖先绘制的图形,因为这样做很高效。
 * 如果场景中的对象不发生运动,观察者的状态也是唯一的,那么这种做法没有问题。但是如果，比如说你希望不断
 * 移动视点，从不同的角度看物体，那么你不可能事先决定对象出现的顺序。

 */
export class CameraPerspectiveEmulator extends CameraEmulator implements IUITool{
    
    onBlur(text: string): void {
        console.log("输入的数据:"+text);
        if(text){
            ShaderTool.setProperty(text, this);
            this._initShaderValue(this.gl);
            this.draw(this.gl);

        }
    }
    onFocus(text: string): void {
        console.log("输入的数据:"+text);
    }
    protected readonly VS: string =
        "attribute vec4 a_Position;\n" +
        "attribute vec4 a_Color;\n" +
        "uniform mat4 u_ProjectMatrix;\n" +
        "uniform mat4 u_ViewMatrix;\n" +
        "varying vec4 v_Color;\n" +
        "void main(){\n" +
        "   v_Color = a_Color;\n" +
        "   gl_Position = u_ProjectMatrix * u_ViewMatrix * a_Position;\n" +
        "}\n";

    private u_ProjectMatrix:WebGLUniformLocation;
    private _projectMatrix:Matrix4;
    near:number = 1.0;
    far:number = 100;
    isFouce: boolean;
    fovy: number = 60;
    aspect: number = 1.0;
    zero:Vector3;
    gl:WebGL2RenderingContext | WebGLRenderingContext;
    private _changeOp:boolean;

    protected _initShaderReference(gl: WebGL2RenderingContext | WebGLRenderingContext) {
        super._initShaderReference(gl);
        this.gl = gl;
        this.zero = Vector3.ZERO;
        this._eyeVec3.z = 5;
        this.zero.z = -100;
        // @ts-ignore
        let program = gl.program;
        this.u_ProjectMatrix = gl.getUniformLocation(program, "u_ProjectMatrix");
    }

    protected _initShaderBuffer(gl: WebGL2RenderingContext | WebGLRenderingContext) {
        let vertexBuffer = gl.createBuffer();
        let colorBuffer = gl.createBuffer();
        if (!vertexBuffer || !colorBuffer) return console.error("init buffer fail");

        let vertexColorArr = new Float32Array([
            0.0, 0.9, 4.0, 0.4, 0.4, 0.4,
            0.0, -0.9, 4.0, 0.4, 0.4, 1.0,
            0.8, 0.5, 4.0, 0.4, 0.4, 0.4,

            -0.2, 0.7, 2.0, 0.4, 0.4, 0.4,
            -0.2, -0.7, 2.0, 0.4, 1.0, 0.4,
            0.6, 0.3, 2.0, 0.4, 0.4, 0.4,

            -0.4, 0.5, 0.0, 1.0, 0.4, 0.4,
            -0.4, -0.5, 0.0, 0.4, 0.4, 0.4,
            0.4, 0.1, 0.0, 1.0, 0.4, 0.4,


        ]);

        let size = vertexColorArr.BYTES_PER_ELEMENT;
        gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, vertexColorArr, gl.STREAM_DRAW);
        gl.vertexAttribPointer(this.a_Position, 3, gl.FLOAT, false, size * 6, 0);
        gl.enableVertexAttribArray(this.a_Position);

        gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, vertexColorArr, gl.STATIC_DRAW);
        gl.vertexAttribPointer(this.a_Color, 3, gl.FLOAT, false, size * 6, size * 3);
        gl.enableVertexAttribArray(this.a_Color);
    }

    protected _initShaderValue(gl: WebGL2RenderingContext | WebGLRenderingContext): void {
        let viewMatrix = this._viewMatrix ||= new Matrix4();
        let up = Vector3.Up;
        let eye = this._eyeVec3;
        let zero = this.zero;
        viewMatrix.setLookAt(
            eye.x, eye.y, eye.z,
            zero.x, zero.y, zero.z,
            up.x, up.y, up.z);
        this._viewMatrix = viewMatrix;
        // this._viewMatrix.multiply(this._moduleMatrix);
        gl.uniformMatrix4fv(this.u_ViewMatrix, false, viewMatrix.elements);

        this._projectMatrix ||= new Matrix4();
        this.near = Math.max(this.near,0.1)
        this.far = Math.max(this.far,0.1)
        this._projectMatrix.setPerspective(this.fovy, this.aspect, this.near, this.far);
        gl.uniformMatrix4fv(this.u_ProjectMatrix, false, this._projectMatrix.elements);
    }

    onKeyDown(gl: WebGL2RenderingContext | WebGLRenderingContext, ev: KeyboardEvent) {
        if(this.isFouce){
            return;
        }
        if(ev.keyCode == Keyboard.C){
            this._changeOp = !this._changeOp;
        }
        if(this._changeOp){
            
           super.onKeyDown(gl, ev);
           return; 
        }
        if (ev.keyCode == Keyboard.A) {
            this._eyeVec3.z -= 0.1;
        }
        if (ev.keyCode == Keyboard.D) {
            this._eyeVec3.z += 0.1;

        }
        if (ev.keyCode == Keyboard.W) {
            this.near += 0.01;
        }
        if (ev.keyCode == Keyboard.S) {
            this.near -= 0.01;
        }

        console.log(`当前的数据 near:${this.near}  far:${this.far}`);
        this._initShaderValue(gl);
        this.draw(gl);
    }


}